//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.example.pcapnative;

import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteOrder;
import java.util.List;
import java.util.regex.Pattern;
import java.util.zip.Adler32;
import java.util.zip.CRC32;

public final class ByteArrays {
    public static final int BYTE_SIZE_IN_BYTES = 1;
    public static final int SHORT_SIZE_IN_BYTES = 2;
    public static final int INT_SIZE_IN_BYTES = 4;
    public static final int LONG_SIZE_IN_BYTES = 8;
    public static final int INET4_ADDRESS_SIZE_IN_BYTES = 4;
    public static final int INET6_ADDRESS_SIZE_IN_BYTES = 16;
    public static final int BYTE_SIZE_IN_BITS = 8;
    private static final Pattern NO_SEPARATOR_HEX_STRING_PATTERN = Pattern.compile("\\A([0-9a-fA-F][0-9a-fA-F])+\\z");
    private static final char[] HEX_CHARS = "0123456789abcdef".toCharArray();
    private static final int[] CRC32C_TABLE = new int[]{0, -227835133, -516198153, 324072436, -946170081, 904991772, 648144872, -724933397, -1965467441, 2024987596, 1809983544, -1719030981, 1296289744, -1087877933, -1401372889, 1578318884, 274646895, -499825556, -244992104, 51262619, -675000208, 632279923, 922689671, -996891772, -1702387808, 1760304291, 2075979607, -1982370732, 1562183871, -1351185476, -1138329528, 1313733451, 549293790, -757723683, -1048117719, 871202090, -416867903, 357341890, 102525238, -193467851, -1436232175, 1477399826, 1264559846, -1187764763, 1845379342, -1617575411, -1933233671, 2125378298, 820201905, -1031222606, -774358714, 598981189, -143008082, 85089709, 373468761, -467063462, -1170599554, 1213305469, 1526817161, -1452612982, 2107672161, -1882520222, -1667500394, 1861252501, 1098587580, -1290756417, -1606390453, 1378610760, -2032039261, 1955203488, 1742404180, -1783531177, -878557837, 969524848, 714683780, -655182201, 205050476, -28094097, -318528869, 526918040, 1361435347, -1555146288, -1340167644, 1114974503, -1765847604, 1691668175, 2005155131, -2047885768, -604208612, 697762079, 986182379, -928222744, 476452099, -301099520, -44210700, 255256311, 1640403810, -1817374623, -2130844779, 1922457750, -1503918979, 1412925310, 1197962378, -1257441399, -350237779, 427051182, 170179418, -129025959, 746937522, -554770511, -843174843, 1070968646, 1905808397, -2081171698, -1868356358, 1657317369, -1241332974, 1147748369, 1463399397, -1521340186, -79622974, 153784257, 444234805, -401473738, 1021025245, -827320098, -572462294, 797665321, -2097792136, 1889384571, 1674398607, -1851340660, 1164749927, -1224265884, -1537745776, 1446797203, 137323447, -96149324, -384560320, 461344835, -810158936, 1037989803, 781091935, -588970148, -1834419177, 1623424788, 1939049696, -2114449437, 1429367560, -1487280117, -1274471425, 1180866812, 410100952, -367384613, -112536529, 186734380, -538233913, 763408580, 1053836080, -860110797, -1572096602, 1344288421, 1131464017, -1323612590, 1708204729, -1749376582, -2065018290, 1988219213, 680717673, -621187478, -911630946, 1002577565, -284657034, 493091189, 238226049, -61306494, -1307217207, 1082061258, 1395524158, -1589280451, 1972364758, -2015074603, -1800104671, 1725896226, 952904198, -894981883, -638100751, 731699698, -11092711, 222117402, 510512622, -335130899, -1014159676, 837199303, 582374963, -790768336, 68661723, -159632680, -450051796, 390545967, 1230274059, -1153434360, -1469116676, 1510247935, -1899042540, 2091215383, 1878366691, -1650582816, -741088853, 565732008, 854102364, -1065151905, 340358836, -433916489, -177076669, 119113024, 1493875044, -1419691417, -1204696685, 1247431312, -1634718085, 1828433272, 2141937292, -1916740209, -483350502, 291187481, 34330861, -262120466, 615137029, -691946490, -980332558, 939183345, 1776939221, -1685949482, -1999470558, 2058945313, -1368168502, 1545135305, 1330124605, -1121741762, -210866315, 17165430, 307568514, -532767615, 888469610, -962626711, -707819363, 665062302, 2042050490, -1948470087, -1735637171, 1793573966, -1104306011, 1279665062, 1595330642, -1384295599};

    private ByteArrays() {
        throw new AssertionError();
    }

    public static byte[] reverse(byte[] array) {
        byte[] rarray = new byte[array.length];

        for(int i = 0; i < array.length; ++i) {
            rarray[i] = array[array.length - i - 1];
        }

        return rarray;
    }

    public static byte getByte(byte[] array, int offset) {
        validateBounds(array, offset, 1);
        return array[offset];
    }

    public static byte[] toByteArray(byte value) {
        return new byte[]{value};
    }

    public static String toHexString(byte value, String separator) {
        return toHexString(toByteArray(value), separator);
    }

    public static short getShort(byte[] array, int offset) {
        return getShort(array, offset, ByteOrder.BIG_ENDIAN);
    }

    public static short getShort(byte[] array, int offset, ByteOrder bo) {
        validateBounds(array, offset, 2);
        if (bo == null) {
            throw new NullPointerException(" bo: " + bo);
        } else {
            return bo.equals(ByteOrder.LITTLE_ENDIAN) ? (short)(array[offset + 1] << 8 | 255 & array[offset]) : (short)(array[offset] << 8 | 255 & array[offset + 1]);
        }
    }

    public static byte[] toByteArray(short value) {
        return toByteArray(value, ByteOrder.BIG_ENDIAN);
    }

    public static byte[] toByteArray(short value, ByteOrder bo) {
        return bo.equals(ByteOrder.LITTLE_ENDIAN) ? new byte[]{(byte)value, (byte)(value >> 8)} : new byte[]{(byte)(value >> 8), (byte)value};
    }

    public static String toHexString(short value, String separator) {
        return toHexString(value, separator, ByteOrder.BIG_ENDIAN);
    }

    public static String toHexString(short value, String separator, ByteOrder bo) {
        return toHexString(toByteArray(value, bo), separator);
    }

    public static int getInt(byte[] array, int offset) {
        return getInt(array, offset, ByteOrder.BIG_ENDIAN);
    }

    public static int getInt(byte[] array, int offset, ByteOrder bo) {
        validateBounds(array, offset, 4);
        if (bo == null) {
            throw new NullPointerException(" bo: " + bo);
        } else {
            return bo.equals(ByteOrder.LITTLE_ENDIAN) ? array[offset + 3] << 24 | (255 & array[offset + 2]) << 16 | (255 & array[offset + 1]) << 8 | 255 & array[offset] : array[offset] << 24 | (255 & array[offset + 1]) << 16 | (255 & array[offset + 2]) << 8 | 255 & array[offset + 3];
        }
    }

    public static int getInt(byte[] array, int offset, int length) {
        return getInt(array, offset, length, ByteOrder.BIG_ENDIAN);
    }

    public static int getInt(byte[] array, int offset, int length, ByteOrder bo) {
        validateBounds(array, offset, length);
        if (length > 4) {
            StringBuilder sb = (new StringBuilder(30)).append("length must be equal or less than ").append(4).append(", but is: ").append(length);
            throw new IllegalArgumentException(sb.toString());
        } else if (bo == null) {
            throw new NullPointerException(" bo: " + bo);
        } else {
            int value = 0;
            if (bo.equals(ByteOrder.LITTLE_ENDIAN)) {
                for(int i = offset + length - 1; i >= offset; --i) {
                    value <<= 8;
                    value |= 255 & array[i];
                }
            } else {
                for(int i = offset; i < offset + length; ++i) {
                    value <<= 8;
                    value |= 255 & array[i];
                }
            }

            return value;
        }
    }

    public static byte[] toByteArray(int value) {
        return toByteArray(value, ByteOrder.BIG_ENDIAN);
    }

    public static byte[] toByteArray(int value, ByteOrder bo) {
        return bo.equals(ByteOrder.LITTLE_ENDIAN) ? new byte[]{(byte)value, (byte)(value >> 8), (byte)(value >> 16), (byte)(value >> 24)} : new byte[]{(byte)(value >> 24), (byte)(value >> 16), (byte)(value >> 8), (byte)value};
    }

    public static byte[] toByteArray(int value, int length) {
        return toByteArray(value, length, ByteOrder.BIG_ENDIAN);
    }

    public static byte[] toByteArray(int value, int length, ByteOrder bo) {
        if (length > 4) {
            StringBuilder sb = (new StringBuilder(30)).append("length must be equal or less than ").append(4).append(", but is: ").append(length);
            throw new IllegalArgumentException(sb.toString());
        } else {
            byte[] arr = new byte[length];
            if (bo.equals(ByteOrder.LITTLE_ENDIAN)) {
                for(int i = 0; i < length; ++i) {
                    arr[length - i - 1] = (byte)(value >> 8 * i);
                }
            } else {
                for(int i = 0; i < length; ++i) {
                    arr[i] = (byte)(value >> 8 * i);
                }
            }

            return arr;
        }
    }

    public static String toHexString(int value, String separator) {
        return toHexString(value, separator, ByteOrder.BIG_ENDIAN);
    }

    public static String toHexString(int value, String separator, ByteOrder bo) {
        return toHexString(toByteArray(value, bo), separator);
    }

    public static long getLong(byte[] array, int offset) {
        return getLong(array, offset, ByteOrder.BIG_ENDIAN);
    }

    public static long getLong(byte[] array, int offset, ByteOrder bo) {
        validateBounds(array, offset, 8);
        if (bo == null) {
            throw new NullPointerException(" bo: " + bo);
        } else {
            return bo.equals(ByteOrder.LITTLE_ENDIAN) ? (long)array[offset + 7] << 56 | (255L & (long)array[offset + 6]) << 48 | (255L & (long)array[offset + 5]) << 40 | (255L & (long)array[offset + 4]) << 32 | (255L & (long)array[offset + 3]) << 24 | (255L & (long)array[offset + 2]) << 16 | (255L & (long)array[offset + 1]) << 8 | 255L & (long)array[offset] : (long)array[offset] << 56 | (255L & (long)array[offset + 1]) << 48 | (255L & (long)array[offset + 2]) << 40 | (255L & (long)array[offset + 3]) << 32 | (255L & (long)array[offset + 4]) << 24 | (255L & (long)array[offset + 5]) << 16 | (255L & (long)array[offset + 6]) << 8 | 255L & (long)array[offset + 7];
        }
    }

    public static byte[] toByteArray(long value) {
        return toByteArray(value, ByteOrder.BIG_ENDIAN);
    }

    public static byte[] toByteArray(long value, ByteOrder bo) {
        return bo.equals(ByteOrder.LITTLE_ENDIAN) ? new byte[]{(byte)((int)value), (byte)((int)(value >> 8)), (byte)((int)(value >> 16)), (byte)((int)(value >> 24)), (byte)((int)(value >> 32)), (byte)((int)(value >> 40)), (byte)((int)(value >> 48)), (byte)((int)(value >> 56))} : new byte[]{(byte)((int)(value >> 56)), (byte)((int)(value >> 48)), (byte)((int)(value >> 40)), (byte)((int)(value >> 32)), (byte)((int)(value >> 24)), (byte)((int)(value >> 16)), (byte)((int)(value >> 8)), (byte)((int)value)};
    }

    public static String toHexString(long value, String separator) {
        return toHexString(value, separator, ByteOrder.BIG_ENDIAN);
    }

    public static String toHexString(long value, String separator, ByteOrder bo) {
        return toHexString(toByteArray(value, bo), separator);
    }

    public static LinkLayerAddress getLinkLayerAddress(byte[] array, int offset, int length) {
        return getLinkLayerAddress(array, offset, length, ByteOrder.BIG_ENDIAN);
    }

    public static LinkLayerAddress getLinkLayerAddress(byte[] array, int offset, int length, ByteOrder bo) {
        validateBounds(array, offset, length);
        if (bo == null) {
            throw new NullPointerException(" bo: " + bo);
        } else {
            return bo.equals(ByteOrder.LITTLE_ENDIAN) ? LinkLayerAddress.getByAddress(reverse(getSubArray(array, offset, length))) : LinkLayerAddress.getByAddress(getSubArray(array, offset, length));
        }
    }

    public static byte[] toByteArray(LinkLayerAddress value) {
        return toByteArray(value, ByteOrder.BIG_ENDIAN);
    }

    public static byte[] toByteArray(LinkLayerAddress value, ByteOrder bo) {
        return bo.equals(ByteOrder.LITTLE_ENDIAN) ? reverse(value.getAddress()) : value.getAddress();
    }

    public static Inet4Address getInet4Address(byte[] array, int offset) {
        return getInet4Address(array, offset, ByteOrder.BIG_ENDIAN);
    }

    public static Inet4Address getInet4Address(byte[] array, int offset, ByteOrder bo) {
        validateBounds(array, offset, 4);
        if (bo == null) {
            throw new NullPointerException(" bo: " + bo);
        } else {
            try {
                return bo.equals(ByteOrder.LITTLE_ENDIAN) ? (Inet4Address)InetAddress.getByAddress(reverse(getSubArray(array, offset, 4))) : (Inet4Address)InetAddress.getByAddress(getSubArray(array, offset, 4));
            } catch (UnknownHostException e) {
                throw new AssertionError(e);
            }
        }
    }

    public static byte[] parseInet4Address(String addr) {
        String[] octetStrs = addr.split("\\.", 4);
        if (octetStrs.length != 4) {
            throw new IllegalArgumentException("Couldn't get an Inet4Address from " + addr);
        } else {
            byte[] octets = new byte[4];

            for(int i = 0; i < octets.length; ++i) {
                String octetStr = octetStrs[i];

                try {
                    int octet = Integer.parseInt(octetStr);
                    if (octet < 0 || octet > 255) {
                        throw new IllegalArgumentException("Couldn't get an Inet4Address from " + addr);
                    }

                    octets[i] = (byte)octet;
                } catch (NumberFormatException var6) {
                    throw new IllegalArgumentException("Couldn't get an Inet4Address from " + addr);
                }
            }

            return octets;
        }
    }

    public static Inet6Address getInet6Address(byte[] array, int offset) {
        return getInet6Address(array, offset, ByteOrder.BIG_ENDIAN);
    }

    public static Inet6Address getInet6Address(byte[] array, int offset, ByteOrder bo) {
        validateBounds(array, offset, 16);
        if (bo == null) {
            throw new NullPointerException(" bo: " + bo);
        } else {
            try {
                return bo.equals(ByteOrder.LITTLE_ENDIAN) ? Inet6Address.getByAddress((String)null, reverse(getSubArray(array, offset, 16)), -1) : Inet6Address.getByAddress((String)null, getSubArray(array, offset, 16), -1);
            } catch (UnknownHostException e) {
                throw new AssertionError(e);
            }
        }
    }

    public static byte[] toByteArray(InetAddress value) {
        return toByteArray(value, ByteOrder.BIG_ENDIAN);
    }

    public static byte[] toByteArray(InetAddress value, ByteOrder bo) {
        return bo.equals(ByteOrder.LITTLE_ENDIAN) ? reverse(value.getAddress()) : value.getAddress();
    }

    public static byte[] getSubArray(byte[] array, int offset, int length) {
        validateBounds(array, offset, length);
        byte[] subArray = new byte[length];
        System.arraycopy(array, offset, subArray, 0, length);
        return subArray;
    }

    public static byte[] getSubArray(byte[] array, int offset) {
        return getSubArray(array, offset, array.length - offset);
    }

    public static String toHexString(byte[] array, String separator) {
        return toHexString(array, separator, 0, array.length);
    }

    public static String toHexString(byte[] array, String separator, int offset, int length) {
        validateBounds(array, offset, length);
        char[] hexChars;
        if (separator.length() != 0) {
            char[] sepChars = separator.toCharArray();
            hexChars = new char[length * 2 + sepChars.length * (length - 1)];
            int cur = 0;

            int i;
            for(i = 0; i < length - 1; ++i) {
                int v = array[offset + i] & 255;
                hexChars[cur] = HEX_CHARS[v >>> 4];
                ++cur;
                hexChars[cur] = HEX_CHARS[v & 15];
                ++cur;

                for(int j = 0; j < sepChars.length; ++j) {
                    hexChars[cur] = sepChars[j];
                    ++cur;
                }
            }

            int v = array[offset + i] & 255;
            hexChars[cur] = HEX_CHARS[v >>> 4];
            hexChars[cur + 1] = HEX_CHARS[v & 15];
        } else {
            hexChars = new char[length * 2];
            int cur = 0;

            for(int i = 0; i < length; ++i) {
                int v = array[offset + i] & 255;
                hexChars[cur] = HEX_CHARS[v >>> 4];
                ++cur;
                hexChars[cur] = HEX_CHARS[v & 15];
                ++cur;
            }
        }

        return new String(hexChars);
    }

    public static short calcChecksum(byte[] data) {
        long sum = 0L;

        for(int i = 1; i < data.length; i += 2) {
            sum += 65535L & (long)getShort(data, i - 1);
        }

        if (data.length % 2 != 0) {
            sum += 65535L & (long)(data[data.length - 1] << 8);
        }

        while(sum >> 16 != 0L) {
            sum = (65535L & sum) + (sum >>> 16);
        }

        return (short)((int)(~sum));
    }

    public static int calcCrc32Checksum(byte[] data) {
        CRC32 crc32 = new CRC32();
        crc32.update(data, 0, data.length);
        return (int)crc32.getValue();
    }

    public static int calcCrc32cChecksum(byte[] data) {
        int c = -1;

        for(int i = 0; i < data.length; ++i) {
            c = CRC32C_TABLE[(c ^ data[i]) & 255] ^ c >>> 8;
        }

        return ~c;
    }

    public static int calcAdler32Checksum(byte[] data) {
        Adler32 adler32 = new Adler32();
        adler32.update(data,0,data.length);
        return (int)adler32.getValue();
    }

    public static byte[] parseByteArray(String hexString, String separator) {
        if (hexString != null && separator != null) {
            if (hexString.startsWith("0x")) {
                hexString = hexString.substring(2);
            }

            String noSeparatorHexString;
            if (separator.length() == 0) {
                if (!NO_SEPARATOR_HEX_STRING_PATTERN.matcher(hexString).matches()) {
                    StringBuilder sb = new StringBuilder(100);
                    sb.append("invalid hex string(").append(hexString).append("), not match pattern(").append(NO_SEPARATOR_HEX_STRING_PATTERN.pattern()).append(")");
                    throw new IllegalArgumentException(sb.toString());
                }

                noSeparatorHexString = hexString;
            } else {
                StringBuilder patternSb = new StringBuilder(60);
                patternSb.append("\\A[0-9a-fA-F][0-9a-fA-F](").append(Pattern.quote(separator)).append("[0-9a-fA-F][0-9a-fA-F])*\\z");
                String patternString = patternSb.toString();
                Pattern pattern = Pattern.compile(patternString);
                if (!pattern.matcher(hexString).matches()) {
                    StringBuilder sb = new StringBuilder(150);
                    sb.append("invalid hex string(").append(hexString).append("), not match pattern(").append(patternString).append(")");
                    throw new IllegalArgumentException(sb.toString());
                }

                noSeparatorHexString = hexString.replaceAll(Pattern.quote(separator), "");
            }

            int arrayLength = noSeparatorHexString.length() / 2;
            byte[] array = new byte[arrayLength];

            for(int i = 0; i < arrayLength; ++i) {
                array[i] = (byte)Integer.parseInt(noSeparatorHexString.substring(i * 2, i * 2 + 2), 16);
            }

            return array;
        } else {
            StringBuilder sb = new StringBuilder();
            sb.append("hexString: ").append(hexString).append(" separator: ").append(separator);
            throw new NullPointerException(sb.toString());
        }
    }

    public static byte[] clone(byte[] array) {
        byte[] clone = new byte[array.length];
        System.arraycopy(array, 0, clone, 0, array.length);
        return clone;
    }

    public static void validateBounds(byte[] arr, int offset, int len) {
        if (arr == null) {
            throw new NullPointerException("arr must not be null.");
        } else if (arr.length == 0) {
            throw new IllegalArgumentException("arr is empty.");
        } else if (len == 0) {
            StringBuilder sb = new StringBuilder(100);
            sb.append("length is zero. offset: ").append(offset).append(", arr: ").append(toHexString(arr, ""));
            throw new IllegalArgumentException(sb.toString());
        } else if (offset < 0 || len < 0 || offset + len > arr.length) {
            StringBuilder sb = new StringBuilder(100);
            sb.append("arr.length: ").append(arr.length).append(", offset: ").append(offset).append(", len: ").append(len).append(", arr: ").append(toHexString(arr, ""));
            throw new ArrayIndexOutOfBoundsException(sb.toString());
        }
    }

    public static byte[] xor(byte[] arr1, byte[] arr2) {
        if (arr1 == null) {
            throw new NullPointerException("arr1 must not be null.");
        } else if (arr2 == null) {
            throw new NullPointerException("arr2 must not be null.");
        } else if (arr1.length != arr2.length) {
            throw new IllegalArgumentException("arr1.length must equal to arr2.length.");
        } else {
            byte[] result = new byte[arr1.length];

            for(int i = 0; i < arr1.length; ++i) {
                result[i] = (byte)(arr1[i] ^ arr2[i]);
            }

            return result;
        }
    }

    public static byte[] concatenate(byte[] arr1, byte[] arr2) {
        byte[] result = new byte[arr1.length + arr2.length];
        System.arraycopy(arr1, 0, result, 0, arr1.length);
        System.arraycopy(arr2, 0, result, arr1.length, arr2.length);
        return result;
    }

    public static byte[] concatenate(List<byte[]> arrs) {
        int length = 0;

        for(byte[] arr : arrs) {
            length += arr.length;
        }

        byte[] result = new byte[length];
        int destPos = 0;

        for(byte[] arr : arrs) {
            System.arraycopy(arr, 0, result, destPos, arr.length);
            destPos += arr.length;
        }

        return result;
    }
}
